#include "Application.h"

void glfw_error_callback(int error, const char *description)
{
    fprintf(stderr, "GLFW Error %d: %s\n", error, description);
}

void Instance::Renderer()
{
    int display_w, display_h;
    glfwGetFramebufferSize(Application::Instantiation().MainWindow, &display_w, &display_h);
    glViewport(0, 0, display_w, display_h);
    glClear(GL_COLOR_BUFFER_BIT);
    ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

    if (Application::Instantiation().Io->ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
    {
        GLFWwindow *backup_current_context = glfwGetCurrentContext();
        ImGui::UpdatePlatformWindows();
        ImGui::RenderPlatformWindowsDefault();
        glfwMakeContextCurrent(backup_current_context);
    }

    glfwSwapBuffers(Application::Instantiation().MainWindow);
}

Application &Application::Instantiation()
{
    static Application app;
    return app;
}

ImGuiIO *Application::GetIO()
{
    return Application::Instantiation().Io;
}

Application::ErrCode Application::Init()
{
    glfwSetErrorCallback(glfw_error_callback);
    if (!glfwInit())
    {
        return ErrCode::GLFW_INIT;
    }
#if defined(IMGUI_IMPL_OPENGL_ES2)
    // GL ES 2.0 + GLSL 100 (WebGL 1.0)
    const char *glsl_version = "#version 330";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#elif defined(IMGUI_IMPL_OPENGL_ES3)
    // GL ES 3.0 + GLSL 300 es (WebGL 2.0)
    const char *glsl_version = "#version 330 es";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
#elif defined(__APPLE__)
    // GL 3.2 + GLSL 150
    const char *glsl_version = "#version 330";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);           // Required on Mac

#else
    // GL 3.0 + GLSL 130
    const char *glsl_version = "#version 330";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
    // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 3.2+ only
    // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
#endif
    // 创建线程池
    Application::Instantiation().ThreadPool = new BS::light_thread_pool(6);
    // 创建GLFW窗口
    glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
    Application::Instantiation().MainWindow = glfwCreateWindow(300, 35, "DealBox", nullptr, nullptr);
    if (Application::Instantiation().MainWindow == nullptr)
    {
        return ErrCode::GLFW_CREATE_WINDOW;
    }
    glfwMakeContextCurrent(Application::Instantiation().MainWindow);
    glfwSwapInterval(1);
    // 设置IMGUI上下文与绑定GLFW窗口
    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    Application::Instantiation().Io = &ImGui::GetIO();
    (void)Application::Instantiation().Io;
    ImFont *font1 = Application::Instantiation().Io->Fonts->AddFontFromFileTTF(
        "Gen Jyuu Gothic Bold.ttf",
        15,
        nullptr,
        Application::Instantiation().Io->Fonts->GetGlyphRangesChineseFull());
    Application::Instantiation().Io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    Application::Instantiation().Io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
    Application::Instantiation().Io->ConfigFlags |= ImGuiConfigFlags_DockingEnable;    // Enable Docking
    Application::Instantiation().Io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
    ImGui::StyleColorsDark();
    ImGui_ImplGlfw_InitForOpenGL(Application::Instantiation().MainWindow, true);
    ImGui_ImplOpenGL3_Init(glsl_version);

    return ErrCode::OK;
}

Application::ErrCode Application::Exec()
{
    GLFWwindow *MainWindow = Application::Instantiation().MainWindow;
    while ((!Application::Instantiation().is_done) && (!glfwWindowShouldClose(MainWindow)))
    {
        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        Application::Instantiation().MainInstance->Draw();
        ImGui::Render();
        Application::Instantiation().MainInstance->Renderer();
    }
    // 释放内存
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    glfwDestroyWindow(MainWindow);
    glfwTerminate();

    return ErrCode::OK;
}

void Application::Quit()
{
    Application::Instantiation().is_done = true;
}

void Application::SetInstance(Instance *instance)
{
    this->MainInstance = instance;
}
